pub(crate) fn main() {
    // 整型溢出
    // 假设有一个 u8 ，它可以存放从 0 到 255 的值。那么当你将其修改为范围之外的值，比如 256，则会发生整型溢出。关于这一行为 Rust 有一些有趣的规则：当在 debug 模式编译时，Rust 会检查整型溢出，若存在这些问题，则使程序在编译时 panic(崩溃,Rust 使用这个术语来表明程序因错误而退出)。
    //
    // 在当使用 --release 参数进行 release 模式构建时，Rust 不检测溢出。相反，当检测到整型溢出时，Rust 会按照补码循环溢出（two’s complement wrapping）的规则处理。简而言之，大于该类型最大值的数值会被补码转换成该类型能够支持的对应数字的最小值。比如在 u8 的情况下，256 变成 0，257 变成 1，依此类推。程序不会 panic，但是该变量的值可能不是你期望的值。依赖这种默认行为的代码都应该被认为是错误的代码。
    //
    // 要显式处理可能的溢出，可以使用标准库针对原始数字类型提供的这些方法：
    //
    // 使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理，例如 wrapping_add
    // 如果使用 checked_* 方法时发生溢出，则返回 None 值
    // 使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
    // 使用 saturating_* 方法使值达到最小值或最大值
    let a: u8 = 255;
    let b = a.wrapping_add(20);
    println!("{}", b);  // 19

    let x = 2.0; // f64
    let y: f32 = 3.0; // f32
    println!("x:{},y:{}", x, y);

    // 断言0.1 + 0.2与0.3相等
    // assert_eq!(0.1 + 0.2, 0.3);

    let abc: (f32, f32, f32) = (0.1, 0.2, 0.3);
    let xyz: (f64, f64, f64) = (0.1, 0.2, 0.3);

    println!("abc (f32)");
    println!("   0.1 + 0.2: {:x}", (abc.0 + abc.1).to_bits());
    println!("         0.3: {:x}", (abc.2).to_bits());
    println!();

    println!("xyz (f64)");
    println!("   0.1 + 0.2: {:x}", (xyz.0 + xyz.1).to_bits());
    println!("         0.3: {:x}", (xyz.2).to_bits());
    println!();

    assert_eq!(abc.0 + abc.1, abc.2);
    assert_eq!(xyz.0 + xyz.1, xyz.2);

    // NaN
    // 对于数学上未定义的结果，例如对负数取平方根 -42.1.sqrt() ，会产生一个特殊的结果：Rust 的浮点数类型使用 NaN (not a number)来处理这些情况。
    //
    // 所有跟 NaN 交互的操作，都会返回一个 NaN，而且 NaN 不能用来比较，下面的代码会崩溃：
    let x = (-42.0_f32).sqrt();
    assert_eq!(x, x);

    let x = (-42.0_f32).sqrt();
    if x.is_nan() {
        println!("未定义的数学行为")
    }

    test2();
}

fn test1() {
    // 数字运算
    // Rust 支持所有数字类型的基本数学运算：加法、减法、乘法、除法和取模运算。下面代码各使用一条 let 语句来说明相应运算的用法：
    // 加法
    let sum = 5 + 10;

    // 减法
    let difference = 95.5 - 4.3;

    // 乘法
    let product = 4 * 30;

    // 除法
    let quotient = 56.7 / 32.2;

    // 求余
    let remainder = 43 % 5;
}

fn test2() {
    // 编译器会进行自动推导，给予twenty i32的类型
    let twenty = 20;
    // 类型标注
    let twenty_one: i32 = 21;
    // 通过类型后缀的方式进行类型标注：22是i32类型
    let twenty_two = 22i32;

    // 只有同样类型，才能运算
    let addition = twenty + twenty_one + twenty_two;
    println!("{} + {} + {} = {}", twenty, twenty_one, twenty_two, addition);

    // 对于较长的数字，可以用_进行分割，提升可读性
    let one_million: i64 = 1_000_000;
    println!("{}", one_million.pow(2));

    // 定义一个f32数组，其中42.0会自动被推导为f32类型
    let forty_twos = [
        42.0,
        42f32,
        42.0_f32,
    ];

    // 打印数组中第一个值，并控制小数位为2位
    println!("{:.2}", forty_twos[0]);
}

fn test3() {
    // 位运算
    // Rust的运算基本上和其他语言一样
    //
    // 运算符	说明
    // & 位与	相同位置均为1时则为1，否则为0
    // | 位或	相同位置只要有1时则为1，否则为0
    // ^ 异或	相同位置不相同则为1，相同则为0
    // ! 位非	把位中的0和1相互取反，即0置为1，1置为0
    // << 左移	所有位向左移动指定位数，右位补0
    // >> 右移	所有位向右移动指定位数，带符号移动（正数补0，负数补1）
    // 二进制为00000010
    let a: i32 = 2;
    // 二进制为00000011
    let b: i32 = 3;

    println!("(a & b) value is {}", a & b);

    println!("(a | b) value is {}", a | b);

    println!("(a ^ b) value is {}", a ^ b);

    println!("(!b) value is {} ", !b);

    println!("(a << b) value is {}", a << b);

    println!("(a >> b) value is {}", a >> b);

    let mut a = a;
    // 注意这些计算符除了!之外都可以加上=进行赋值 (因为!=要用来判断不等于)
    a <<= b;
    println!("(a << b) value is {}", a);
}

fn test4() {
    // 序列(Range)
    // Rust 提供了一个非常简洁的方式，用来生成连续的数值，例如 1..5，生成从 1 到 4 的连续数字，不包含 5 ；1..=5，生成从 1 到 5 的连续数字，包含 5，它的用途很简单，常常用于循环中：
    for i in 1..=5 {
        println!("{}", i);
    }

    for i in 'a'..='z' {
        println!("{}", i);
    }
}

fn test5() {
    // 有理数和复数
    // Rust 的标准库相比其它语言，准入门槛较高，因此有理数和复数并未包含在标准库中：
    //
    // 有理数和复数
    // 任意大小的整数和任意精度的浮点数
    // 固定精度的十进制小数，常用于货币相关的场景
    // 好在社区已经开发出高质量的 Rust 数值库：num。
    //
    // 按照以下步骤来引入 num 库：
    //
    // 创建新工程 cargo new complex-num && cd complex-num
    // 在 Cargo.toml 中的 [dependencies] 下添加一行 num = "0.4.0"
    // 将 src/main.rs 文件中的 main 函数替换为下面的代码
    // 运行 cargo run
    let a = Complex { re: 2.1, im: -1.2 };
    let b = Complex::new(11.1, 22.2);
    let result = a + b;

    println!("{} + {}i", result.re, result.im)
}

fn test6() {
    // 字符类型(char)
    // 字符，对于没有其它编程经验的新手来说可能不太好理解（没有编程经验敢来学 Rust 的绝对是好汉），但是你可以把它理解为英文中的字母，中文中的汉字。
    //
    // 下面的代码展示了几个颇具异域风情的字符：
    let c = 'z';
    let z = 'ℤ';
    let g = '国';
    let heart_eyed_cat = '😻';
}

fn test7() {
    // 布尔(bool)
    // Rust 中的布尔类型有两个可能的值：true 和 false，布尔值占用内存的大小为 1 个字节：
    let t = true;

    let f: bool = false; // 使用类型标注,显式指定f的类型

    if f {
        println!("这是段毫无意义的代码");
    }
}

fn test8() {
    // 语句和表达式
    // Rust 的函数体是由一系列语句组成，最后由一个表达式来返回值，例如：
    let x = x + 1; // 语句
    let y = y + 5; // 语句
    x + y // 表达式

    // 对于 Rust 语言而言，这种基于语句（statement）和表达式（expression）的方式是非常重要的，
    // 你需要能明确的区分这两个概念, 但是对于很多其它语言而言，这两个往往无需区分。基于表达式是函数式语言的重要特征，表达式总要返回值。
}

fn test9() {
    // 函数
    // Rust 的函数我们在之前已经见过不少，跟其他语言几乎没有什么区别。
    // 因此本章的学习之路将轻松和愉快，骚年们，请珍惜这种愉快，下一章你将体验到不一样的 Rust。
    //
    // 在函数界，有一个函数只闻其名不闻其声，可以止小孩啼！在程序界只有 hello,world! 可以与之媲美，它就是 add 函数：
    //
    //
    //
    fn add(i: i32, j: i32) -> i32 {
        i + j
    }

    fn plus_or_minus(x: i32) -> i32 {
        if x > 5 {
            return x - 5;
        }
        x + 5
    }

    let x = plus_or_minus(5);

    println!("The value of x is: {}", x);
}


